# DBSCAN算法     
import matplotlib.pyplot as plt
import open3d as o3d
import numpy as np

ply_point_cloud = o3d.data.PLYPointCloud()
pcd = o3d.io.read_point_cloud(ply_point_cloud.path)

# 调试日志 把日志配置成Debug模式
with o3d.utility.VerbosityContextManager(
        o3d.utility.VerbosityLevel.Debug) as cm:
    # pcd.cluster_dbscan() DBSCAN 聚类函数    DBSCAN算法     https://zhuanlan.zhihu.com/p/336501183
    #                       参数 eps 邻域半径  min_points 形成一个 “簇” 所需的最小点数  print_progress=True：在终端显示聚类进度条
    #                       返回值为-1是噪声数据
    labels = np.array(pcd.cluster_dbscan(eps=0.02, min_points=10, print_progress=True))

# 获取最大簇标签
max_label = labels.max()
print(f"点云共有 {max_label + 1} 簇")

# plt.get_cmap("tab20") 获取一个包含20种颜色的色板
colors = plt.get_cmap("tab20")(labels / (max_label if max_label > 0 else 1))

# 把噪声数据设置成黑色
colors[labels < 0] = 0

# 给点云赋值颜色
pcd.colors = o3d.utility.Vector3dVector(colors[:, :3])

# 显示
o3d.visualization.draw_geometries([pcd],
                                  zoom=0.455,
                                  front=[-0.4999, -0.1659, -0.8499],
                                  lookat=[2.1813, 2.0619, 2.0999],
                                  up=[0.1204, -0.9852, 0.1215])